Eng_Lab 02 - ROS2 Actions
Lab. 02 - ROS2 Actions
1. What are ROS2 Actions?
Actions are one of the communication types in ROS2 designed for tasks that take longer to complete. They consist of three parts: goal, feedback, and result.
Actions are built on topics and services. Their operation is similar to services, with two differences: - They can be stopped before completion. - They provide continuous feedback during operation, whereas a service informs about the result only once at the end of execution.
Goal - serves to initiate the action. It has service functionality - to call and respond whether the action was successfully started.
Feedback - data published by the action server during operation. Typically, it informs about the current progress of the action, such as the remaining distance to travel, estimated remaining time, or the percentage of completion.
Result - the action server’s final response regarding the action’s outcome. It usually contains a binary answer on whether the requested action was successful and the precision with which the action was performed.
2. Environment Setup
Before starting the work, it is necessary to prepare the environment: download the Docker image and create a container based on it.
The image required for today’s exercises is based on osrf/ros:humble-desktop-full
but includes packages necessary for the tasks. The image can be downloaded from this link or using the command:
wget --content-disposition --no-check-certificate https://chmura.put.poznan.pl/s/qnlGDi1XeWicyFo/download
Load the downloaded image using the following command, providing the appropriate path:
docker load < path/to/file.tar.gz
Then, proceed to create the container using the scripts prepared for those using only CPU or equipped with Nvidia GPU. Download the relevant script using wget
, for example.
By default, the container is named ARM_02. NOTE! The scripts, when executed, remove a container with this name before creating a new one.
Using the Container
After each computer restart, remember to invoke:
xhost +local:root
A new terminal can be attached to the container using the command:
docker exec -it ARM_02 bash
3. Course Objective
The goal of the exercises will be to create an action that moves the robot a specified distance from the obstacle in front of it, also providing the time to complete the task and the minimum accuracy required. The feedback will include information about the current distance from the obstacle and the estimated time remaining to complete the action. As a result, the server will inform whether the requirements were met, what the final accuracy and distance from the goal are, and how long the procedure took.
4. Creating Actions
Before we start working on the above task, it’s worth familiarizing ourselves with defining actions using a simpler example - calculating the Fibonacci sequence.
Creating a New Package
To create a new package, from the /arm_ws/src
level, run the command:
ros2 pkg create --build-type ament_cmake fibonacci_sequence_action
It is also necessary to create an action
directory and define the action structure in it:
cd /arm_ws/src/fibonacci_sequence_action
mkdir action && cd action
touch Fibonacci.action
Modify the Fibonacci.action
file (e.g., using nano
, gedit
, or VS code
):
int32 order
---
int32[] sequence
---
int32[] partial_sequence
where order is the action’s goal, sequence is the result, and partial_sequence is the feedback.
With the action structure defined, add it to the ROS2 internal interface code generation pipeline. To do this, modify the CMakeLists.txt
file (before the ament_package()
line) to include:
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
"action/Fibonacci.action"
)
Also, add the required dependencies to the package.xml
file:
<buildtool_depend>rosidl_default_generators</buildtool_depend>
<depend>action_msgs</depend>
<member_of_group>rosidl_interface_packages</member_of_group>
At this stage, it should be possible to build the action definition:
cd /arm_ws
source /opt/ros/humble/setup.bash
colcon build --symlink-install
If the build was successful, you can view the action definition from the ROS2 interface:
source /arm_ws/install/setup.bash
ros2 interface show fibonacci_sequence_action/action/Fibonacci
Preparing the Action Server Script
Knowing that the new package is built and ROS2 provides an action structure, we can start writing the action server script.
Start by creating a scripts
folder and a fibonacci_action_server.py
file:
cd /arm_ws/src/fibonacci_sequence_action/
mkdir scripts && cd scripts
touch fibonacci_action_server.py
The fibonacci_action_server.py
file should be modified as follows:
#!/usr/bin/env python3
import time
import rclpy
from rclpy.action import ActionServer
from rclpy.node import Node
from fibonacci_sequence_action.action import Fibonacci
class FibonacciActionServer(Node):
def __init__(self):
super().__init__('fibonacci_action_server')
self._action_server = ActionServer(
self,
Fibonacci,'fibonacci',
self.execute_callback)
self.get_logger().info('Fibonacci Action Server is running...')
def execute_callback(self, goal_handle):
self.get_logger().info('Executing goal...')
= Fibonacci.Feedback()
feedback_msg = [0, 1]
feedback_msg.partial_sequence
for i in range(1, goal_handle.request.order):
feedback_msg.partial_sequence.append(+ feedback_msg.partial_sequence[i-1])
feedback_msg.partial_sequence[i] self.get_logger().info('Feedback: {0}'.format(feedback_msg.partial_sequence))
goal_handle.publish_feedback(feedback_msg)1)
time.sleep(
goal_handle.succeed()
= Fibonacci.Result()
result = feedback_msg.partial_sequence
result.sequence return result
def main(args=None):
=args)
rclpy.init(args
= FibonacciActionServer()
fibonacci_action_server
rclpy.spin(fibonacci_action_server)
if __name__ == '__main__':
main()
Make sure to mark this file as executable:
chmod +x fibonacci_action_server.py
You will also need to add the path scripts/fibonacci_action_server.py
and the packages rclpy
and ament_cmake_python
to the CMakeLists.txt
file:
find_package(ament_cmake_python REQUIRED)
find_package(rclpy REQUIRED)
install(PROGRAMS
scripts/fibonacci_action_server.pyDESTINATION lib/${PROJECT_NAME}
)
as well as the corresponding dependencies to the package.xml
file:
<buildtool_depend>ament_cmake_python</buildtool_depend>
<depend>rclpy</depend>
The work on the action server is complete; now you can build the package and run it:
cd /arm_ws
colcon build --symlink-install
source install/setup.bash
ros2 run fibonacci_sequence_action fibonacci_action_server.py
In a separate terminal, you can check the list of available actions:
ros2 action list
and send an action goal:
ros2 action send_goal --feedback /fibonacci fibonacci_sequence_action/action/Fibonacci "{order: 10}"
If there is an error regarding the lack of an executable file, delete the
build
,install
, andlog
folders, and then rebuild the workspace:rm -r /arm_ws/build /arm_ws/install /arm_ws/log source /opt/ros/humble/setup.bash colcon build --symlink-insall
5. Independent Task
As part of the task, prepare an action that meets the requirements from Section 3. To do this, use the simulation:
cd /arm_ws
source install/setup.bash
ros2 launch arm02 arm02_world.launch.py
It provides two topics: - /laser_scan
(sensor_msgs/msg/LaserScan) - /cmd_vel
(geometry_msgs/msg/Twist)
The first informs about the distance from the obstacle, while the second should be used for linear motion (in the x-axis).
Support for writing subscribers in ROS2 can be found here.
The action should be defined as follows:
float32 goal_distance
float32 timeout
float32 precision
---
bool succeeded
float32 final_precision
float32 total_time
---
float32 current_distance
float32 estimated_time
NOTE! The action file name must start with a capital letter and contain only letters and numbers.
Hint: How to subscribe to a topic and execute an action simultaneously?
Placing a loop in the action execution method will cause the program to stop reading messages from the /laser_scan topic.
To handle this, you can use the
spin_once
method, passing the node on which the spin should be executed (self
, which is the action node).An alternative solution is to use a multithreaded executor instead of the one provided by default in rclpy. More information and an example of usage can be found here.
On eKursy, please provide: - The action server script (please change the extension to .txt) - A screenshot of the terminal with visible feedback - Screenshots of the terminal with visible results (in the case of exceeding the timeout and when the action was successfully executed)
Based on: Creating an action and Writing an action server and client (Python) from docs.ros.org.